{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Example Sample Hotel and Flight Booker Agent \n",
    "\n",
    "This solution will help you book flight tickets and hotel.  The scenario is a trip London Heathrow LHR Feb 20th 2024 to New York JFK returning Feb 27th 2025 flying economy with British Airways only. I want a stay in a Hilton hotel in New York please provide costs for the flight and hotel'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Initialize the Azure AI Agent Service and get configuration information from **.env**\n",
    "\n",
    "### **.env** \n",
    "\n",
    "Create a .env file \n",
    "\n",
    "**.env** contains the connection string of Azure AI Agent Service, the model used by AOAI, and the corresponding Google API Search service API, ENDPOINT, etc.\n",
    "\n",
    "- **AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME** = \"Your Azure AI Agent Service Model Deployment Name\"\n",
    "\n",
    "[**NOTE**] You will need a model with 100,000 Rate Limit (Tokens per minute)  Rate Limit of 600 (Request per minute)\n",
    "\n",
    "  You can get model in Azure AI Foundry - Model and Endpoint. \n",
    "\n",
    "\n",
    "- **AZURE_AI_AGENT_PROJECT_CONNECTION_STRING** = \"Your Azure AI Agent Service Project Connection String\"\n",
    "\n",
    "  You can get the project connection string in your project overview in  AI ​​Foundry Portal Screen.\n",
    "\n",
    "- **SERPAPI_SEARCH_API_KEY** = \"Your SERPAPI Search API KEY\"\n",
    "- **SERPAPI_SEARCH_ENDPOINT** = \"Your SERPAPI Search Endpoint\"\n",
    "\n",
    "To get the Model Deployment Name and Project Connection String of Azure AI Agent Service, you need to create Azure AI Agent Service. It is recommended to use [this template](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Ffosteramanda%2Fazure-agent-quickstart-templates%2Frefs%2Fheads%2Fmaster%2Fquickstarts%2Fmicrosoft.azure-ai-agent-service%2Fstandard-agent%2Fazuredeploy.json) to create it directly （***Note:*** Azure AI Agent Service is currently set in a limited region. It is recommended that you refer to [this link](https://learn.microsoft.com/en-us/azure/ai-services/agents/concepts/model-region-support) to set the region)\n",
    "\n",
    "Agent needs to access SERPAPI. It is recommended to register using [this link](https://serpapi.com/searches). After registration, you can obtain a unique API KEY and ENDPOINT"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Setup \n",
    "\n",
    "To run this notebook, you will need to install the following libraries. Here is a list of the required libraries and the corresponding pip install commands:\n",
    "\n",
    "azure-identity: For Azure authentication.\n",
    "requests: For making HTTP requests.\n",
    "semantic-kernel: For the semantic kernel framework (assuming this is a custom or specific library, you might need to install it from a specific source or repository)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install azure-identity\n",
    "!pip install requests\n",
    "!pip install semantic-kernel\n",
    "!pip install --upgrade semantic_kernel\n",
    "!pip install azure-cli\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Explanation: \n",
    "import asyncio: This imports the asyncio module, which provides support for asynchronous programming in Python. It allows you to write concurrent code using the async and await syntax.\n",
    "from typing import Annotated: This imports the Annotated type from the typing module. Annotated is used to add metadata to type hints, which can be useful for various purposes such as validation, documentation, or tooling."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "import asyncio\n",
    "from typing import Annotated"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Explanation:\n",
    "\n",
    "Load your .env file setting and resources please ensure you have added your keys and setting and created a local .env file."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "from dotenv import load_dotenv\n",
    "\n",
    "# Load environment variables from .env file\n",
    "load_dotenv()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Login to Azure \n",
    "\n",
    "You Now need to login into Azure Open a terminal and run the `az login` command"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Explanation:\n",
    "\n",
    "Import Statement: from azure.identity.aio import DefaultAzureCredential: This imports the DefaultAzureCredential class from the azure.identity.aio module. The aio part of the module name indicates that it is designed for asynchronous operations.\n",
    "\n",
    "Purpose of DefaultAzureCredential: The DefaultAzureCredential class is part of the Azure SDK for Python. It provides a default way to authenticate with Azure services. It attempts to authenticate using multiple methods in a specific order, such as environment variables, managed identity, and Azure CLI credentials.\n",
    "\n",
    "Asynchronous Operations:The aio module indicates that the DefaultAzureCredential class supports asynchronous operations. This means you can use it with asyncio to perform non-blocking authentication requests."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from azure.identity.aio import DefaultAzureCredential"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Explanation:\n",
    "from semantic_kernel.agents.azure_ai import AzureAIAgent, AzureAIAgentSettings: This imports the AzureAIAgent and AzureAIAgentSettings classes from the semantic_kernel.agents.azure_ai module. These classes are likely used to configure and interact with an AI agent provided by Azure.\n",
    "\n",
    "from semantic_kernel.contents.chat_message_content import ChatMessageContent: This imports the ChatMessageContent class from the semantic_kernel.contents.chat_message_content module. This class is likely used to handle the content of chat messages.\n",
    "\n",
    "from semantic_kernel.contents.utils.author_role import AuthorRole: This imports the AuthorRole class from the semantic_kernel.contents.utils.author_role module. This class is likely used to define the role of the author in a chat message (e.g., user, assistant).\n",
    "\n",
    "from semantic_kernel.functions.kernel_function_decorator import kernel_function: This imports the kernel_function decorator from the semantic_kernel.functions.kernel_function_decorator module. This decorator is likely used to mark functions as kernel functions, which can be used within the semantic kernel framework.\n",
    "\n",
    "# Purpose of the Imports:\n",
    "These imports set up the necessary components for working with an AI agent and handling chat messages within the semantic kernel framework. Here's a brief overview of each component:\n",
    "\n",
    "AzureAIAgent: This class is likely used to create and manage an AI agent that interacts with Azure AI services.\n",
    "\n",
    "AzureAIAgentSettings: This class is likely used to configure settings for the AzureAIAgent, such as authentication credentials and service endpoints.\n",
    "\n",
    "ChatMessageContent: This class is likely used to represent the content of chat messages, including text, metadata, and other relevant information.\n",
    "\n",
    "AuthorRole: This class is likely used to define the role of the author in a chat message, such as whether the message was sent by the user or the AI assistant.\n",
    "\n",
    "kernel_function: This decorator is likely used to mark functions as kernel functions, which can be used within the semantic kernel framework. Kernel functions are typically used to perform specific tasks or operations within the framework."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantic_kernel.agents.azure_ai import AzureAIAgent, AzureAIAgentSettings\n",
    "from semantic_kernel.contents.chat_message_content import ChatMessageContent\n",
    "from semantic_kernel.contents.utils.author_role import AuthorRole\n",
    "from semantic_kernel.functions.kernel_function_decorator import kernel_function"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Explanation:\n",
    "\n",
    "This is a class imported from the semantic_kernel.agents.azure_ai module. It is used to configure settings for an AI agent that interacts with Azure AI services.\n",
    "\n",
    "create() Method: The create() method is a class method of AzureAIAgentSettings. It is used to create and initialize an instance of AzureAIAgentSettings with default or predefined settings.\n",
    "\n",
    "ai_agent_settings Variable: The variable ai_agent_settings is assigned the instance of AzureAIAgentSettings created by the create() method. This instance contains the configuration settings needed to set up and use an Azure AI agent.\n",
    "\n",
    "# Purpose:\n",
    "The purpose of this line is to create a configuration object (ai_agent_settings) that holds the necessary settings for an Azure AI agent. These settings might include authentication credentials, service endpoints, and other configuration parameters required to interact with Azure AI services."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ai_agent_settings = AzureAIAgentSettings.create()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Explanation:\n",
    "import requests: This statement imports the requests library, which is a popular third-party library in Python used for making HTTP requests.\n",
    "\n",
    "Purpose: The requests library simplifies the process of sending HTTP requests and handling responses. It provides a user-friendly interface for interacting with web services and APIs.\n",
    "\n",
    "Common Use Cases: Sending HTTP Requests: You can use the requests library to send various types of HTTP requests, such as GET, POST, PUT, DELETE, etc.\n",
    "\n",
    "Handling Responses:The library makes it easy to handle responses, including reading response content, headers, status codes, and more.\n",
    "Working with APIs:\n",
    "\n",
    "The requests library is commonly used to interact with RESTful APIs, allowing you to send data to and retrieve data from web services."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Explanation:\n",
    "This is a variable that stores the API key for accessing a SERP (Search Engine Results Page) API service. An API key is a unique identifier used to authenticate requests associated with your account.\n",
    "\n",
    "Purpose: The purpose of this line is to store the API key in a variable so that it can be used to authenticate requests to the SERP API service. The API key is required to access the service and perform searches.\n",
    "How to Get a SERP API Key: To get a SERP API key, follow these general steps at https://serpapi.com (the exact steps may vary depending on the specific SERP API service you are using):\n",
    "\n",
    "Choose a SERP API Service: There are several SERP API services available, such as SerpAPI, Google Custom Search JSON API, and others. Choose the one that best fits your needs.\n",
    "\n",
    "Sign Up for an Account: Go to the website of the chosen SERP API service and sign up for an account. You may need to provide some basic information and verify your email address.\n",
    "\n",
    "Create an API Key: After signing up, log in to your account and navigate to the API section or dashboard. Look for an option to create or generate a new API key.\n",
    "Copy the API Key to your .env file."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "SERP_API_KEY='SERPAPI_SEARCH_API_KEY'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Explanation:\n",
    "BASE_URL: This is a variable that stores the base URL for the SERP API endpoint. The variable name BASE_URL is a convention used to indicate that this URL is the starting point for making API requests.\n",
    "'https://serpapi.com/search':\n",
    "\n",
    "This is the actual URL string assigned to the BASE_URL variable. It represents the endpoint for performing search queries using the SERP API.\n",
    "\n",
    "# Purpose:\n",
    "The purpose of this line is to define a constant that holds the base URL for the SERP API. This URL will be used as the starting point for constructing API requests to perform search operations.\n",
    "\n",
    "# Usage:\n",
    "By defining the base URL in a variable, you can easily reuse it throughout your code whenever you need to make requests to the SERP API. This makes your code more maintainable and reduces the risk of errors from hardcoding the URL in multiple places. The current example is https://serpapi.com/search?engine=bing which is using Bing search API. Different API can be selected at https://Serpapi.com"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "BASE_URL = 'https://serpapi.com/search?engine=bing'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Explanation:\n",
    "\n",
    "This is where you agent code is located.\n",
    "\n",
    "Class Definition: class BookingPlugin:: Defines a class named BookingPlugin that contains methods for booking hotels and flights.\n",
    "Docstring: \"\"\"Booking Plugin for customers\"\"\": A docstring that describes the purpose of the BookingPlugin class.\n",
    "Hotel Booking Method:\n",
    "\n",
    "@kernel_function(description=\"booking hotel\"): A decorator that describes the function as a kernel function for booking hotels.\n",
    "def booking_hotel(self, query: Annotated[str, \"The name of the city\"], check_in_date: Annotated[str, \"Hotel Check-in Time\"], check_out_date: Annotated[str, \"Hotel Check-out Time\"]) -> Annotated[str, \"Return the result of booking hotel information\"]:: Defines a method for booking hotels with annotated parameters and return type.\n",
    "\n",
    "The method constructs a dictionary of parameters for the hotel booking request and sends a GET request to the SERP API. It checks the response status and returns the hotel properties if successful, or None if the request failed.\n",
    "\n",
    "Flight Booking Method: @kernel_function(description=\"booking flight\"): A decorator that describes the function as a kernel function for booking flights.\n",
    "def booking_flight(self, origin: Annotated[str, \"The name of Departure\"], destination: Annotated[str, \"The name of Destination\"], outbound_date: Annotated[str, \"The date of outbound\"], return_date: Annotated[str, \"The date of Return_date\"]) -> Annotated[str, \"Return the result of booking flight information\"]:: Defines a method for booking flights with annotated parameters and return type.\n",
    "\n",
    "The method constructs dictionaries of parameters for the outbound and return flight requests and sends GET requests to the SERP API. It checks the response status and appends the flight information to the result string if successful, or prints an error message if the request failed. The method returns the result string containing the flight information.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define Booking Plugin\n",
    "class BookingPlugin:\n",
    "    \"\"\"Booking Plugin for customers\"\"\"\n",
    "\n",
    "    @kernel_function(description=\"booking hotel\")\n",
    "    def booking_hotel(self, query: Annotated[str, \"The name of the city\"], check_in_date: Annotated[str, \"Hotel Check-in Time\"], check_out_date: Annotated[str, \"Hotel Check-out Time\"]) -> Annotated[str, \"Return the result of booking hotel information\"]:\n",
    "        \"\"\"\n",
    "        Function to book a hotel.\n",
    "        Parameters:\n",
    "        - query: The name of the city\n",
    "        - check_in_date: Hotel Check-in Time\n",
    "        - check_out_date: Hotel Check-out Time\n",
    "        Returns:\n",
    "        - The result of booking hotel information\n",
    "        \"\"\"\n",
    "\n",
    "        # Define the parameters for the hotel booking request\n",
    "        params = {\n",
    "            \"engine\": \"google_hotels\",\n",
    "            \"q\": query,\n",
    "            \"check_in_date\": check_in_date,\n",
    "            \"check_out_date\": check_out_date,\n",
    "            \"adults\": \"1\",\n",
    "            \"currency\": \"GBP\",\n",
    "            \"gl\": \"uk\",\n",
    "            \"hl\": \"en\",\n",
    "            \"api_key\": SERP_API_KEY\n",
    "        }\n",
    "\n",
    "        # Send the GET request to the SERP API\n",
    "        response = requests.get(BASE_URL, params=params)\n",
    "\n",
    "        # Check if the request was successful\n",
    "        if response.status_code == 200:\n",
    "            # Parse the response content as JSON\n",
    "            response = response.json()\n",
    "            # Return the properties from the response\n",
    "            return response[\"properties\"]\n",
    "        else:\n",
    "            # Return None if the request failed\n",
    "            return None\n",
    "\n",
    "    @kernel_function(description=\"booking flight\")\n",
    "    def booking_flight(self, origin: Annotated[str, \"The name of Departure\"], destination: Annotated[str, \"The name of Destination\"], outbound_date: Annotated[str, \"The date of outbound\"], return_date: Annotated[str, \"The date of Return_date\"]) -> Annotated[str, \"Return the result of booking flight information\"]:\n",
    "        \"\"\"\n",
    "        Function to book a flight.\n",
    "        Parameters:\n",
    "        - origin: The name of Departure\n",
    "        - destination: The name of Destination\n",
    "        - outbound_date: The date of outbound\n",
    "        - return_date: The date of Return_date\n",
    "        - airline: The preferred airline carrier\n",
    "        - hotel_brand: The preferred hotel brand\n",
    "        Returns:\n",
    "        - The result of booking flight information\n",
    "        \"\"\"\n",
    "        \n",
    "        # Define the parameters for the outbound flight request\n",
    "        go_params = {\n",
    "            \"engine\": \"google_flights\",\n",
    "            \"departure_id\": \"destination\",\n",
    "            \"arrival_id\": \"origin\",\n",
    "            \"outbound_date\": \"outbound_date\",\n",
    "            \"return_date\": \"return_date\",\n",
    "            \"currency\": \"GBP\",\n",
    "            \"hl\": \"en\",\n",
    "            \"airline\": \"airline\",\n",
    "            \"hotel_brand\": \"hotel_brand\",\n",
    "            \"api_key\": \"SERP_API_KEY\"\n",
    "        }\n",
    " \n",
    " \n",
    " \n",
    "        print(go_params)\n",
    "\n",
    "        # Send the GET request for the outbound flight\n",
    "        go_response = requests.get(BASE_URL, params=go_params)\n",
    "\n",
    "        # Initialize the result string\n",
    "        result = ''\n",
    "\n",
    "        # Check if the outbound flight request was successful\n",
    "        if go_response.status_code == 200:\n",
    "            # Parse the response content as JSON\n",
    "            response = go_response.json()\n",
    "            # Append the outbound flight information to the result\n",
    "            result += \"# outbound \\n \" + str(response)\n",
    "        else:\n",
    "            # Print an error message if the request failed\n",
    "            print('error!!!')\n",
    "\n",
    "        # Define the parameters for the return flight request\n",
    "        back_params = {\n",
    "            #\"engine\": \"google_flights\",\n",
    "            \"departure_id\": destination,\n",
    "            \"arrival_id\": origin,\n",
    "            \"outbound_date\": outbound_date,\n",
    "            \"return_date\": return_date,\n",
    "            \"currency\": \"GBP\",\n",
    "            \"hl\": \"en\",\n",
    "            \"api_key\": SERP_API_KEY\n",
    "        }\n",
    "\n",
    "        # Send the GET request for the return flight\n",
    "        back_response = requests.get(BASE_URL, params=back_params)\n",
    "\n",
    "        # Check if the return flight request was successful\n",
    "        if back_response.status_code == 200:\n",
    "            # Parse the response content as JSON\n",
    "            response = back_response.json()\n",
    "            # Append the return flight information to the result\n",
    "            result += \"\\n # return \\n\" + str(response)\n",
    "        else:\n",
    "            # Print an error message if the request failed\n",
    "            print('error!!!')\n",
    "\n",
    "        # Print the result\n",
    "        print(result)\n",
    "\n",
    "        # Return the result\n",
    "        return result\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Explanation:\n",
    "Import Statements: Import necessary modules for Azure credentials, AI agent, chat message content, author role, and kernel function decorator.\n",
    "\n",
    "Asynchronous Context Manager: async with (DefaultAzureCredential() as creds, AzureAIAgent.create_client(credential=creds, conn_str=\"...\") as client,):: This sets up an asynchronous context manager to handle Azure credentials and create an AI agent client.\n",
    "\n",
    "Agent Name and Instructions: AGENT_NAME = \"BookingAgent\": Defines the name of the agent.\n",
    "AGENT_INSTRUCTIONS = \"\"\"...\"\"\": Provides detailed instructions for the agent on how to handle booking requests.\n",
    "\n",
    "Create Agent Definition: agent_definition = await client.agents.create_agent(...): Creates an agent definition with the specified model, name, and instructions.\n",
    "\n",
    "Create AzureAI Agent: agent = AzureAIAgent(...): Creates an AzureAI agent using the client and agent definition.\n",
    "\n",
    "Add Booking Plugin: agent.kernel.add_plugin(BookingPlugin(), plugin_name=\"booking\"): Adds the BookingPlugin to the agent's kernel.\n",
    "\n",
    "Create Thread: thread = await client.agents.create_thread(): Creates a new thread for the agent.\n",
    "\n",
    "User Inputs: user_inputs = [\"...\"]: Defines a list of user inputs for the agent to process.\n",
    "\n",
    "Process User Inputs:For each user input, add it as a chat message, invoke the agent, and print the agent's response.\n",
    "Clean Up:\n",
    "\n",
    "In the finally block, delete the thread and agent to clean up resources."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import necessary modules\n",
    "from azure.identity.aio import DefaultAzureCredential\n",
    "from semantic_kernel.agents.azure_ai import AzureAIAgent, AzureAIAgentSettings\n",
    "from semantic_kernel.contents.chat_message_content import ChatMessageContent\n",
    "from semantic_kernel.contents.utils.author_role import AuthorRole\n",
    "from semantic_kernel.functions.kernel_function_decorator import kernel_function\n",
    "\n",
    "# Azure AI Setting\n",
    "async with (\n",
    "     DefaultAzureCredential() as creds,\n",
    "            AzureAIAgent.create_client(\n",
    "                credential=creds,\n",
    "                conn_str=ai_agent_settings.project_connection_string.get_secret_value(),\n",
    "            ) as client,\n",
    "):    \n",
    "    \n",
    "    # Define the agent's name and instructions\n",
    "    AGENT_NAME = \"BookingAgent\"\n",
    "    AGENT_INSTRUCTIONS = \"\"\"\n",
    "    You are a booking agent, help me to book flights or hotels.\n",
    "\n",
    "    Thought: Understand the user's intention and confirm whether to use the reservation system to complete the task.\n",
    "\n",
    "    Action:\n",
    "    - If booking a flight, convert the departure name and destination name into airport codes.\n",
    "    - If booking a hotel or flight, use the corresponding API to call. Ensure that the necessary parameters are available. If any parameters are missing, use default values or assumptions to proceed.\n",
    "    - If it is not a hotel or flight booking, respond with the final answer only.\n",
    "    - Output the results using a markdown table:\n",
    "    - For flight bookings, separate the outbound and return contents and list them in the order of Departure_airport Name | Airline | Flight Number | Departure Time | Arrival_airport Name | Arrival Time | Duration | Airplane | Travel Class | Price (USD) | Legroom | Extensions | Carbon Emissions (kg).\n",
    "    - For hotel bookings, list them in the order of Properties Name | Properties description | check_in_time | check_out_time | prices | nearby_places | hotel_class | gps_coordinates.\n",
    "\"\"\"\n",
    "\n",
    "    # Create agent definition with the specified model, name, and instructions\n",
    "    agent_definition = await client.agents.create_agent(\n",
    "        model=ai_agent_settings.model_deployment_name,\n",
    "        name=AGENT_NAME,\n",
    "        instructions=AGENT_INSTRUCTIONS,\n",
    "    )\n",
    "\n",
    "    # Create the AzureAI Agent using the client and agent definition\n",
    "    agent = AzureAIAgent(\n",
    "        client=client,\n",
    "        definition=agent_definition,\n",
    "        # Optionally configure polling options\n",
    "        # polling_options=RunPollingOptions(run_polling_interval=timedelta(seconds=1)),\n",
    "    )\n",
    "\n",
    "    # Add the BookingPlugin to the agent's kernel\n",
    "    agent.kernel.add_plugin(BookingPlugin(), plugin_name=\"booking\")\n",
    "\n",
    "    # Create a new thread for the agent\n",
    "    thread = await client.agents.create_thread()\n",
    "\n",
    "    # This is your prompt for the activity or task you want to complete \n",
    "    # Define user inputs for the agent to process we have provided some example prompts to test and validate \n",
    "    user_inputs = [\n",
    "        # \"Can you tell me the round-trip air ticket from  London to New York JFK aiport, the departure time is February 17, 2025, and the return time is February 23, 2025\"\n",
    "        # \"Book a hotel in New York from Feb 20,2025 to Feb 24,2025\"\n",
    "        \"Help me book flight tickets and hotel for the following trip London Heathrow LHR Feb 20th 2025 to New York JFK returning Feb 27th 2025 flying economy with British Airways only. I want a stay in a Hilton hotel in New York please provide costs for the flight and hotel\"\n",
    "        # \"I have a business trip from London LHR to New York JFK on Feb 20th 2025 to Feb 27th 2025, can you help me to book a hotel and flight tickets\"\n",
    "    ]\n",
    "\n",
    "    try:\n",
    "        # Process each user input\n",
    "        for user_input in user_inputs:\n",
    "            # Add the user input as a chat message\n",
    "            await agent.add_chat_message(\n",
    "                thread_id=thread.id, message=ChatMessageContent(role=AuthorRole.USER, content=user_input)\n",
    "            )\n",
    "            print(f\"# User: '{user_input}'\")\n",
    "            # Invoke the agent for the specified thread\n",
    "            async for content in agent.invoke(\n",
    "                thread_id=thread.id,\n",
    "                temperature=0.2,  # Override the agent-level temperature setting with a run-time value\n",
    "            ):\n",
    "                if content.role != AuthorRole.TOOL:\n",
    "                    print(f\"# Agent: {content.content}\")\n",
    "    finally:\n",
    "        # Clean up by deleting the thread and agent\n",
    "        await client.agents.delete_thread(thread.id)\n",
    "        await client.agents.delete_agent(agent.id)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "3.12.1",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.1"
  },
  "polyglot_notebook": {
   "kernelInfo": {
    "defaultKernelName": "csharp",
    "items": [
     {
      "aliases": [],
      "name": "csharp"
     }
    ]
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
